#pragma once

#include "SideUserObject.h"
#include "RandomInterface.h"
#include "ENSideElement.h"
#include <vector>
#include <set>

using std::vector;
using std::set;
using std::string;

class RayLine;
class ENRadiationHeatFluxUserObject :
public SideUserObject,
public RandomInterface
{
public:
	ENRadiationHeatFluxUserObject(const InputParameters & parameters);
	Real getTemBar(int i) const {return _temperature_pow4_bar[i];}
	Real getRadiationFlux(int i) const { return _flux_radiation[i]; }
	Real getRadiationFlux(const Elem * elem) const { return _flux_radiation[Find_i(elem)]; }
	Real getRadiationFluxJacobi(const Elem * elem)  const  {return _flux_radiation_jacobi[Find_i(elem)];}
	Real getEpsilon(const Elem * elem)  const  {return _all_element[Find_i(elem)]->_absorptivity;}
	vector<Real> getRadiationFluxList() const { return _flux_radiation; }
	vector<Real> getRadiationFluxJacobiList() const { return _flux_radiation_jacobi; }
	vector<Point> getCenterPointList() const { return _center_point_list; }
	vector<Real> getEpsilonList() const { return _epsilon_list; }

	~ENRadiationHeatFluxUserObject();

protected :
	virtual void initialSetup();
	virtual void initialize();
	virtual void finalize();
	virtual void execute();
	virtual void threadJoin(const UserObject & uo){};

	virtual void computeRadiationFlux();
	void ompComputeRD(int n_threads, int max_reflect_count);
	void Deal_with_BSMC(int BSMC);
	void RD_normalized(bool is_seal);
	int Find_i(const Elem * elem) const;
	bool Is_Shelter_Engineer(int i_index, int j_index, Point i_centre, Point j_centre);

	void print_mesh_to_file();
	void print_T_to_file();
	void print_flux_to_file();

	vector<ENSideElement*> _all_element;

	int _max_reflect_count;
	int _devide_side;
	vector<Real> _transmissivity;
	vector<Real> _absorptivity;
	string _filename;
	bool _is_seal;
	bool _mpi_or_omp;
	int _n_threads;
	int _BSMC;
	bool _write_or_read;

	set<SubdomainID> _block_ids;
	
	const VariableValue &_temperature;
	vector<Real> _temperature_pow4_bar;
	vector<Real> _temperature_pow3_bar;
	vector<Real> _temperature_bar;
	vector<Real> _flux_radiation;
	vector<Real> _flux_radiation_jacobi;
	vector<Real> _epsilon_list;
	vector<Point> _center_point_list;

};
template<> InputParameters validParams<ENRadiationHeatFluxUserObject>();
